<?php

/**
 * Created by PhpStorm.
 * User: Mr.Lee
 * Date: 2017/5/6
 * Time: 上午10:39
 */

namespace Alipay;
class Alipayobj
{
    private $appid;
    private $rsaPrivateKeyFilePath;
    private $rsaPrivateKey;
    private $cmmb_key;
    private $postCharset;
    private $AUTH_URL;
    private $fileCharset;
    const OAUTH_PREFIX = 'https://openauth.alipay.com/oauth2/';
    //沙箱环境
//    const OAUTH_PREFIX = 'https://openauth.alipaydev.com/oauth2/';
    const OAUTH_AUTHORIZE_URL = 'publicAppAuthorize.htm?';
    const OAUTH_URL = 'https://openapi.alipay.com/gateway.do';
    const CMMB_ALIPAY_URL = 'http://scp.yufu99.com/scanpay-api/api/unifiedOrder20';//民生通道

    public function __construct($options)
    {
        $this->appid = isset($options['appid']) ? $options['appid'] : '';
        $this->rsaPrivateKey = isset($options['rsaPrivateKey']) ? $options['rsaPrivateKey'] : '';
        $this->cmmb_key = isset($options['cmmb_key']) ? $options['cmmb_key'] : '';

    }

    public function getcmmbpay($data)
    {
        $result = $this->http_post(self::CMMB_ALIPAY_URL, $data, true);
        return $result;
    }

    /*
     * 支付宝支付签名
     */
    public function getcmmbpaysignature($post_data)
    {
        $key = $this->cmmb_key;
        ksort($post_data);

        $o = "";
        foreach ($post_data as $k => $v) {
            $o .= "$k=" . ($v) . "&";
        }
        $post_data = substr($o, 0, -1);
        $post_data_temp = $post_data . $key;
        $signIn = strtoupper(md5($post_data_temp));
        return $signIn;

    }

    /*
     * 支付宝跳转授权
     */
    public function getOauthRedirect($callback, $state = '', $scope = 'auth_userinfo')
    {
        return self::OAUTH_PREFIX . self::OAUTH_AUTHORIZE_URL . 'app_id=' . $this->appid . '&scope=' . $scope . '&redirect_uri=' . urlencode($callback);
    }

    public function getOauthAccessToken($param)
    {
        $code = isset($_GET['code']) ? $_GET['code'] : '';
        if (!$code) return false;

        $result = $this->http_post($this->AUTH_URL, $param);


    }

    public function generateSign($params, $signType = "RSA")
    {
        return $this->sign($this->getSignContent($params), $signType);
    }

    public function rsaSign($params, $signType = "RSA")
    {
        return $this->sign($this->getSignContent($params), $signType);

    }

    public function rsaSign2($params, $signType = "RSA")
    {
        return $this->sign($this->getSignContentUrlencode($params), $signType);
    }

    public function getSignContent($params)
    {
        ksort($params);

        $stringToBeSigned = "";
        $i = 0;
        foreach ($params as $k => $v) {
            if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {

                // 转换成目标字符集
                $v = $this->characet($v, $this->postCharset);

                if ($i == 0) {
                    $stringToBeSigned .= "$k" . "=" . "$v";
                } else {
                    $stringToBeSigned .= "&" . "$k" . "=" . "$v";
                }
                $i++;
            }
        }

        unset ($k, $v);
        return $stringToBeSigned;
    }

    public function getCertSN($cert)
    {
        $ssl = openssl_x509_parse($cert);
        $SN = md5($this->array2string(array_reverse($ssl['issuer'])) . $ssl['serialNumber']);
        return $SN;
    }

    /**
     * 提取根证书序列号
     * @param $cert  根证书
     * @return string|null
     */
    public function getRootCertSN($alipayRootCertContent)
    {
        $array = explode("-----END CERTIFICATE-----", $alipayRootCertContent);
        $SN = null;
        for ($i = 0; $i < count($array) - 1; $i++) {
            $ssl[$i] = openssl_x509_parse($array[$i] . "-----END CERTIFICATE-----");
            if (strpos($ssl[$i]['serialNumber'], '0x') === 0) {
                $ssl[$i]['serialNumber'] = $this->hex2dec($ssl[$i]['serialNumber']);
            }
            if ($ssl[$i]['signatureTypeLN'] == "sha1WithRSAEncryption" || $ssl[$i]['signatureTypeLN'] == "sha256WithRSAEncryption") {
                if ($SN == null) {
                    $SN = md5($this->array2string(array_reverse($ssl[$i]['issuer'])) . $ssl[$i]['serialNumber']);
                } else {

                    $SN = $SN . "_" . md5($this->array2string(array_reverse($ssl[$i]['issuer'])) . $ssl[$i]['serialNumber']);
                }
            }
        }
        return $SN;
    }

    private function hex2dec($hex)
    {
        $dec = 0;
        $len = strlen($hex);
        for ($i = 1; $i <= $len; $i++) {
            $dec = bcadd($dec, bcmul(strval(hexdec($hex[$i - 1])), bcpow('16', strval($len - $i))));
        }
        return $dec;
    }

    private function array2string($array)
    {
        $string = [];
        if ($array && is_array($array)) {
            foreach ($array as $key => $value) {
                $string[] = $key . '=' . $value;
            }
        }
        return implode(',', $string);
    }

    //此方法对value做urlencode
    public function getSignContentUrlencode($params)
    {
        ksort($params);

        $stringToBeSigned = "";
        $i = 0;
        foreach ($params as $k => $v) {
            if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {

                // 转换成目标字符集
                $v = $this->characet($v, $this->postCharset);

                if ($i == 0) {
                    $stringToBeSigned .= "$k" . "=" . urlencode($v);
                } else {
                    $stringToBeSigned .= "&" . "$k" . "=" . urlencode($v);
                }
                $i++;
            }
        }

        unset ($k, $v);
        return $stringToBeSigned;
    }

    //对字段进行签名 默认rsa
    public function alonersaSign($data, $privatekey, $signType = "RSA", $keyfromfile = false)
    {

        if (!$keyfromfile) {
            $priKey = $privatekey;
            $res = "-----BEGIN RSA PRIVATE KEY-----\n" .
                wordwrap($priKey, 64, "\n", true) .
                "\n-----END RSA PRIVATE KEY-----";
        } else {
            $priKey = file_get_contents($privatekey);
            $res = openssl_get_privatekey($priKey);
        }

        ($res) or die('您使用的私钥格式错误，请检查RSA私钥配置');

        if ("RSA2" == $signType) {
            openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA256);
        } else {
            openssl_sign($data, $sign, $res);
        }

        if ($keyfromfile) {
            openssl_free_key($res);
        }
        $sign = base64_encode($sign);
        return $sign;
    }

    public function sign($data, $signType = "RSA")
    {
        if ($this->checkEmpty($this->rsaPrivateKeyFilePath)) {
            $priKey = $this->rsaPrivateKey;

            $res = "-----BEGIN RSA PRIVATE KEY-----\n" .
                wordwrap($priKey, 64, "\n", true) .
                "\n-----END RSA PRIVATE KEY-----";

        } else {
            $priKey = file_get_contents($this->rsaPrivateKeyFilePath);
            $res = openssl_get_privatekey($priKey);
        }

        ($res) or die('您使用的私钥格式错误，请检查RSA私钥配置');

        if ("RSA2" == $signType) {

            openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA256);
        } else {
            openssl_sign($data, $sign, $res);
        }

        if (!$this->checkEmpty($this->rsaPrivateKeyFilePath)) {
            openssl_free_key($res);
        }
        $sign = base64_encode($sign);
        return $sign;
    }

    protected function checkEmpty($value)
    {
        if (!isset($value))
            return true;
        if ($value === null)
            return true;
        if (trim($value) === "")
            return true;

        return false;
    }


    public function scanpay($param)
    {
        $sj = $this->http_post(self::OAUTH_URL, $param);
        return $sj;
    }

    public function upload_file($param)
    {
        $sj = $this->http_post(self::OAUTH_URL, $param, true);
        return $sj;
    }

    private function characet($data, $targetCharset)
    {

        if (!empty($data)) {
            $fileType = $this->fileCharset;
            if (strcasecmp($fileType, $targetCharset) != 0) {
                $data = mb_convert_encoding($data, $targetCharset, $fileType);
                //				$data = iconv($fileType, $targetCharset.'//IGNORE', $data);
            }
        }


        return $data;
    }

    public function getuid($param)
    {
        $sj = $this->http_post(self::OAUTH_URL, $param);
        return $sj;


    }

    private function http_post($url, $param, $post_file = false)
    {

        $oCurl = curl_init();
        if (stripos($url, "https://") !== FALSE) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
        }
        if (PHP_VERSION_ID >= 50500 && class_exists('\CURLFile')) {
            $is_curlFile = true;
        } else {
            $is_curlFile = false;
            if (defined('CURLOPT_SAFE_UPLOAD')) {
                curl_setopt($oCurl, CURLOPT_SAFE_UPLOAD, false);
            }
        }
        if (is_string($param)) {
            $strPOST = $param;
        } elseif ($post_file) {

            if ($is_curlFile) {
                foreach ($param as $key => $val) {

                    if (substr($val, 0, 1) == '@') {

                        $param[$key] = new \CURLFile(realpath(substr($val, 1)));

                    }
                }

            }
            $strPOST = $param;

        } else {
            $aPOST = array();
            foreach ($param as $key => $val) {
                $aPOST[] = $key . "=" . urlencode($val);
            }
            $strPOST = join("&", $aPOST);

        }
//        return $strPOST;

        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($oCurl, CURLOPT_POST, true);
        curl_setopt($oCurl, CURLOPT_POSTFIELDS, $strPOST);
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);

        if (intval($aStatus["http_code"]) == 200) {
            return $sContent;
        } else {
            return false;
        }
    }
}